import HtmlMarker from "../../component/models/HtmlMarker";

//shape地图中的POI碰撞管理器
export default class PoiCollisionManager{
    private static poiMap: Map<Object, Array<HtmlMarker>> = new Map<Object, Array<HtmlMarker>>();
    private static tileMap: Map<string, Object> = new Map<string, Object>();

    public static addPoiTile(tileJson, htmlMarker: HtmlMarker): boolean{ //poiArray: Array<HtmlMarker>
        let poiArray = PoiCollisionManager.poiMap.get(tileJson);
        if(!poiArray){
            poiArray = new Array<HtmlMarker>();

            let tileStr = JSON.stringify(tileJson);
            PoiCollisionManager.tileMap.set(tileStr, tileJson);
        }

        let maxPoiNum = 15; //一个瓦片中最大的POI数量
        if(poiArray.length >= maxPoiNum){
            return false;
        }
        poiArray.push(htmlMarker);
        PoiCollisionManager.poiMap.set(tileJson, poiArray);
        return true;
    }

    public static getPoiArrayFromTile(tileJson){
        let poiArray = PoiCollisionManager.poiMap.get(tileJson);
        return poiArray;
    }

    public static getTile(tileStr: string){
        return PoiCollisionManager.tileMap.get(tileStr);
    }

    public static removePoiTile(tileJson){
        PoiCollisionManager.poiMap.delete(tileJson);

        let tileStr = JSON.stringify(tileJson);
        PoiCollisionManager.tileMap.delete(tileStr);
    }

    public static executeCollision(){
        //对每个瓦片内部的POI做碰撞检测
        PoiCollisionManager.poiMap.forEach((value: Array<HtmlMarker>, key) => {
            PoiCollisionManager.executeCollisionInTile(value, key);
            key['isChecked'] = false;
        });

        //对相邻瓦片的POI做碰撞检测
        PoiCollisionManager.poiMap.forEach((value: Array<HtmlMarker>, key) => {

            PoiCollisionManager.poiMap.forEach((otherValue: Array<HtmlMarker>, otherKey) => {
                if( otherKey['isChecked'] == true){
                    return;
                }
                // if(Math.abs(key['x'] - otherKey['x']) + Math.abs(key['y'] - otherKey['y']) == 1){ //检测是相邻的瓦片
                if(Math.abs(key['x'] - otherKey['x']) == 1 || Math.abs(key['y'] - otherKey['y']) == 1){ //检测是相邻的瓦片
                    for(let i=0; i<value.length; i++){
                        let marker = value[i];
                        if(marker.isCoveredByFog() == true){ //被雾遮挡了，不用参与碰撞检测
                            continue;
                        }
                        if(marker.element.style.opacity == '0.0'){ // .visible == false
                            continue;
                        }

                        let isCollide = false;
                        loopLabel:
                        for(let j=0; j<otherValue.length; j++){
                            let otherMarker = otherValue[j];
                            if(otherMarker.element.style.opacity == '0.0'){ //otherMarker.visible == false
                                continue;
                            }
                            isCollide = PoiCollisionManager.isColliding(marker, otherMarker);
                            if(isCollide){
                                marker.element.style.opacity = '0.0';
                                break loopLabel;
                            }
                        }

                    }
                }
            });

            key['isChecked'] = true;
        });

    }

    public static executeCollisionInTile(value: Array<HtmlMarker>, key){
        for(let i=0; i<value.length; i++){
            let marker = value[i];
            if(marker.isCoveredByFog() == true){ //被雾遮挡了，不用参与碰撞检测
                continue;
            }

            let isCollide = false;
            loopLabel:
            for(let j=i+1; j<value.length; j++){
                let otherMarker = value[j];
                if(i == j || otherMarker.element.style.opacity == '0.0'){
                    continue;
                }
                isCollide = PoiCollisionManager.isColliding(marker, otherMarker);
                if(isCollide == true){
                    marker.element.style.opacity = '0.0';
                    break loopLabel;
                }
            }

            if(isCollide == false){
                marker.element.style.opacity = '1.0';
            }
        }
    }

    private static isColliding(object1: HtmlMarker, object2: HtmlMarker) {
        var rect1 = object1.element.getBoundingClientRect();
        var rect2 = object2.element.getBoundingClientRect();
      
        if(rect1.left > rect2.right){
            return false;
        }
        if(rect1.right < rect2.left){
            return false;
        }
        if(rect1.top > rect2.bottom){
            return false;
        }
        if(rect1.bottom < rect2.top){
            return false;
        }
        return true;
      }
      
}